#include <iostream>
#include <string>
#include <stdlib.h>
#include <sys/epoll.h>
#include <unistd.h>

#include"log.hpp"  

//eoll最大监听数
static const int max_epoll_size = 128 ; 
static const int epfd_befor_init = -1 ; 

// Epoller是否要设置为单例模式？ 


class Epoller
{
private:

    // epoll句柄
    int _epfd ; 
    static Epoller* _eppoller ; 

    Epoller()
    :_epfd(epfd_befor_init) 
    {

    }

    void epollCreatePacked()
    {
        _epfd = epoll_create(max_epoll_size) ; 

        if(_epfd < 0 )
        {
            LOG(FATAL, "epoll create falied")  ; 
            exit(-10) ; 
        }
    }

public:

    static Epoller* getInstance()
    {
        static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER ; 

        if(_eppoller == nullptr)
        {
            pthread_mutex_lock(&lock);

            if(_eppoller == nullptr)
            {
                _eppoller = new Epoller ; 
                _eppoller->epollCreatePacked() ;
                LOG(INFO, "Epoller create sucess") ;
            }

            pthread_mutex_unlock(&lock) ; 
        }

        return _eppoller  ;         
    }

    // bool 返回判断操作是否成功执行
    // 为什么不直接把op设置为EPOLL_CTL_ADD  
    bool addEollEverntPacked(int fd, uint32_t event, int op)
    {
        epoll_event  ev ; 
        ev.events = event ; 
        ev.data.fd = fd ; 
        int adjust = epoll_ctl(_epfd, op, fd, &ev) ;
        if(adjust < 0)
        {
            LOG(WARNING, "add epoll event failed") ; 
            return false ; 
        }

        return true ; 
    }

    bool deleteEpollEventPacked(int fd)
    {
        int adjust = epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, nullptr) ; 

        if(adjust < 0) 
        {
            return false ; 
            LOG(WARNING, "delete epoll event falied") ; 
        }
        return true ;
    }

    // 用于服务器主文件描述符监听  //一次最多返回num个就绪事件
    int epollWaitPacked(epoll_event* revs, int num, int timeout)
    {
        return epoll_wait(_epfd, revs, num, timeout) ; 
    }

    ~Epoller() 
    {
        close(_epfd) ; 
    }

} ;


Epoller* Epoller::_eppoller = nullptr ; 